#include "dbimpl.h"
#include "stringutil.h"
#include "statement.h"
#include "tableinfo.h"
#include "fieldinfo.h"

CDatabaseImpl::CDatabaseImpl(void)
{
	
}
CDatabaseImpl::~CDatabaseImpl(void)
{

}
std_method_impl CDatabaseImpl::Init(int Argc, basic_tchar* Argv[], IBase* pRot, IBase* pBase)
{
	HRESULT		hr = S_OK;

	return hr;
}
std_method_impl CDatabaseImpl::Uninit()
{
	HRESULT		hr = S_OK;

	return hr;
}
std_method_impl CDatabaseImpl::Start(_pinstance hInstance, UINT uType)
{
	HRESULT		hr = S_OK;

	return hr;
}
std_method_impl CDatabaseImpl::Stop(UINT uExitCode)
{
	HRESULT		hr = S_OK;

	return hr;
}

std_method_impl CDatabaseImpl::SetOption(LPCWSTR lpszName, LPCWSTR lpszValue)
{
	HRESULT		hr = S_OK;

	m_lstOption[lpszName] = lpszValue;

	return hr;
}
std_method_impl CDatabaseImpl::Connect()
{
	HRESULT		hr = S_OK;
	LPCWSTR		szFile = NULL;
	CHAR  szFileUtf8[MAX_PATH + 1] = {0x00};
	std::map<std::wstring, std::wstring>::iterator it;
	for (it = m_lstOption.begin(); it != m_lstOption.end(); it++){
		if (it->first.compare(L"database") == 0){
			szFile = it->second.c_str();
		}
	}

	string strPath;
	int rc = sqlite3_open(strPath.c_str(), &m_pDB);
	rc_assert(rc == SQLITE_OK, E_FAIL)

	sqlite3_busy_timeout(m_pDB, 10000);

	return hr;
}
std_method_type_impl(UINT) CDatabaseImpl::IsValid()
{
	return S_SUCCESS;
}
std_method_impl CDatabaseImpl::Close()
{
	HRESULT		hr = S_OK;

	int rc =  sqlite3_close(m_pDB);
	rc_assert(rc == SQLITE_OK, E_FAIL)
	return hr;
}


std_method_impl CDatabaseImpl::CreateStatement(IStatement** ppStatement)
{
	CStatementImpl* p = ALLOC_NEW CStatementImpl(m_pDB);
	rc_assert(p != NULL, E_FAIL)
	return p->QueryInterface(IID_IStatement, (void **)ppStatement);
}

std_method_type_impl(UINT) CDatabaseImpl::IsTableExist(LPCSTR lpszName)
{
	char szSQL[1024] = {0x00};
	int rc = SQLITE_OK;

	sprintf(szSQL,
		"select count(*) from sqlite_master where type='table' and name='%s'",
		lpszName);

	StmtPtr pStmt = compile(m_pDB, szSQL);
	rc_assert(pStmt != NULL, E_FAIL)

	rc = sqlite3_step(pStmt);
	rc_assert(rc == SQLITE_ROW, S_ERROR)

	rc = sqlite3_column_int(pStmt, 0);
	rc_assert(rc == SQLITE_OK, S_SUCCESS)

	return S_ERROR;
}
std_method_impl CDatabaseImpl::GetTableInfo(LPCSTR lpszName, ITableInfo** ppTableInfo)
{
	int nRet = 0;
	char szSQL[128] = {0x00};
	const char *pTail = NULL;
	std::string strTypeName;
	std::string strNotNull;
	std::string strPK;

	sprintf(szSQL, "%s%s%s", "PRAGMA table_info('", lpszName, "')");
	
	StmtPtr pStmt = compile(m_pDB, szSQL);
	rc_assert(pStmt.m_p != NULL,E_FAIL)

	while (sqlite3_step(pStmt) == SQLITE_ROW){
		_lComPtr<IFieldInfo> pFieldInfo;
		pFieldInfo.dispose();

		int nFlag = 0;

		HRESULT hr  = CXFieldInfo::CreateInstance((IFieldInfo**)&pFieldInfo);
		rc_assert_continue(hr == S_OK)

		pFieldInfo->SetName((char *)sqlite3_column_text(pStmt, FIELD_NAME_INDEX));
		strTypeName = (char *)sqlite3_column_text(pStmt, FIELD_TYPE_INDEX);
		strNotNull = (char *)sqlite3_column_text(pStmt, FIELD_ISNULL_INDEX);
		strPK = (char *)sqlite3_column_text(pStmt, FIELD_PK_INDEX);
		if (atoi(strNotNull.c_str()) == FIELD_IS_NOTNULL){
			nFlag = FF_NOT_NULL;
		}
		if (atoi(strPK.c_str()) == FIELD_IS_PK){
			nFlag = FF_PRI_KEY;
		}
		pFieldInfo->SetFlag(nFlag);
		pFieldInfo->SetTypeName(strTypeName.c_str());
		pFieldInfo->SetType(sqlite_string_to_type(strTypeName.c_str()));
		pFieldInfo->SetDefault("0");
		(*ppTableInfo)->Add(pFieldInfo);
	}

	return S_OK;
}
std_method_impl CDatabaseImpl::UpdateTable(ITableInfo* pTableInfo)
{
	HRESULT		hr = S_OK;

	rc_assert(pTableInfo != NULL, E_FAIL)

	UINT uloop = 0;
	UINT uCount = pTableInfo->GetFieldCount();
	
	rc_assert(uCount != 0, S_OK)

	string strCreateSql = "CREATE TABLE IF NOT EXISTS ";
	strCreateSql += pTableInfo->GetName();
	strCreateSql += "(";
	
	for (uloop = 0; uloop < uCount; uloop++)
	{
		_lComPtr<IFieldInfo> pField;
		pField.dispose();

		string strField;

		pTableInfo->GetField(uloop, &pField.m_p);

		if (pField != NULL)
		{
			strField += pField->GetName();
			strField += " ";
			strField += pField->GetTypeName();
			strField += " ";

			if (FF_PRI_KEY & pField->GetFlag())
			{
				strField += "PRIMARY KEY ";
			}

			if (FF_AUTO_INCREMENT & pField->GetFlag())
			{
				strField += "AUTOINCREMENT ";
			}
	
			if (FF_NOT_NULL & pField->GetFlag() )
			{
				strField += "NOT NULL ";
			}
			strField += ",";
			strCreateSql += strField;
		}
	}

	strCreateSql += ")";

	_lComPtr<IStatement> Statement;
	CreateStatement(&Statement.m_p);
	Statement->Execute(strCreateSql.c_str(), strCreateSql.length());
	return S_OK;
}
std_method_impl CDatabaseImpl::CreateTableInfo(LPCSTR lpszName, ITableInfo** ppTableInfo)
{
	return CXTableInfo::CreateInstance(lpszName,ppTableInfo);
}











